﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EFTest2
{
    class Program
    {
        static void Main(string[] args)
        {

            UserRole model = new UserRole();

            model.ID = "1111";

            Role role = new Role();

            role.ID = "sdf";

            role.Name = "新增";

            model.RoleID = role;


            //Dictionary<string, PropertyInfo> dics = getPropertyInfos<UserRole>(model);


            //修改用户名称

            //string[] paths = new string[] { "UserID", "Name"};

            //object temp= dics[paths[0]].GetValue(model);

            //dics["UserID.Name"].SetValue(temp, "测试设置路径值");


            //Console.Write("修改后的值:" + model.UserID.Name);

            // SetValue<UserRole>(model, "UserID.ID","测试设置路径值");

            Console.Write("修改后的值:" + GetValue<UserRole>(model, "RoleID"));
            
            Console.ReadKey();


        }



        /// <summary>
        /// 设置值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="fieldPath"></param>
        private static void SetValue<T>(T model,string fieldPath,object value)
        {

            if(fieldPath==null||fieldPath=="")
            {
                
                return;

            }

            Dictionary<string, PropertyInfo> dics = getPropertyInfos<T>(model);

            string[] paths = fieldPath.Split('.');
            
            string key = "";

            object parent=model;

            object result;
            

            for(int i=0;i<paths.Length;i++)
            {

                if(key!="")
                {
                    key = key +"."+ paths[i];

                }
                else
                {
                    key = paths[i];
                }
                
                if (dics.ContainsKey(key))
                {
                  
                    if(i!=paths.Length-1)
                    {

                        result = dics[key].GetValue(parent);


                        if (result==null)
                        {

                            result = Activator.CreateInstance(dics[key].PropertyType);

                        }

                        dics[key].SetValue(parent, result);
                        
                        parent = result;
                        


                    }
                    else
                    {

                        dics[key].SetValue(parent, value);


                    }
                   

                }



            }



        }

        

        /// <summary>
        /// 获取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="fieldPath"></param>
        /// <returns></returns>
        private static object GetValue<T>(T model, string fieldPath)
        {

            if (fieldPath == null || fieldPath == "")
            {

                return null;

            }


            if (model == null)
            {


                return null;

            }


            Dictionary<string, PropertyInfo> dics = getPropertyInfos<T>(model);

            string[] paths = fieldPath.Split('.');

            string key = "";

            object parent = model;

            object result=null;


            for (int i = 0; i < paths.Length; i++)
            {

                if (key != "")
                {
                    key = key + "." + paths[i];

                }
                else
                {
                    key = paths[i];
                }


                if (dics.ContainsKey(key))
                {

                    result = dics[key].GetValue(parent);

                    if (result == null)
                    {

                        return null;


                    }


                    parent = result;



                }
                else
                {

                    return null;
                }





            }

            return result;
        }



            /// <summary>
            /// 获取类型的所有属性及值
            /// </summary>
            /// <param name="type"></param>
        public static Dictionary<string, PropertyInfo> getPropertyInfos<T>(T model)
        {


            if(model==null)
            {


                return null;

            }

            Dictionary<string, PropertyInfo> propertys = new Dictionary<string, PropertyInfo>();


            foreach (PropertyInfo property in model.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
            {


               

                Console.Write("Name:" + property.Name + "  value: " + property.GetValue(model)+"\n");

                property.GetValue(model);

                if (property.PropertyType.IsPrimitive || property.PropertyType.Name=="String")
                {
                    propertys.Add(property.Name, property);

                    Console.Write("Name:" + property.Name + "  value: " + property.GetValue(model) + "\n");


                    continue;

                }
                else
                {
                    propertys.Add(property.Name, property);

                    getChildPropertys(model,property,"", propertys, 0);


                }


            }
            
            return propertys;


            }


        /// <summary>
        /// 获取属性的属性列表，可以设置获取层级，默认三级
        /// </summary>
        /// <param name="parent">父级属性</param>
        /// <param name="propertys">属性列表</param>
        /// <param name="level">层次</param>
        private static void getChildPropertys<T>(T model,PropertyInfo parent,string parentName, Dictionary<string, PropertyInfo> propertys,int level)
        {

            level++;

            if(level>3||model==null)
            {

                return;
            }

            parentName = parentName + parent.Name;


            foreach (PropertyInfo property in parent.PropertyType.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
            {

                propertys.Add(parentName + "." + property.Name, property);


                if (property.PropertyType.IsPrimitive || property.PropertyType.Name == "String")
                {

                  
                    continue;

                }
                else
                {
                    
                    getChildPropertys(model, property, parentName, propertys, level);


                }




            }
               


        }

        
        public static object HackType(object value, Type conversionType)
        {
            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null)
                    return null;
                System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, conversionType);
        }
    }
}
